package com.contest.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.contest.entity.BettingRecord;
import com.contest.entity.GamingQuiz;
import com.contest.entity.MerchantInfo;
import com.contest.entity.UserInfo;
import com.contest.service.*;
import com.contest.util.DateUtil;
import com.contest.util.RandomUtil;
import com.contest.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class SettlementService {

    @Autowired
    private GamingDataService gamingDataService;
    @Autowired
    private GamingOddsService gamingOddsService;
    @Autowired
    private GamingQuizService gamingQuizService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    MerchantInfoService merchantInfoService;
    @Autowired
    BettingRecordService bettingRecordService;

//    @Scheduled(cron = "0/1 * * * * ?")
    @Transactional
    void gamingSettlement() throws ParseException {
        Jedis redis = redisUtil.getJedis();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        EntityWrapper<GamingQuiz> quizEntityWrapper = new EntityWrapper<>();
        quizEntityWrapper.addFilter("fd_is_settlement={0}", 0);
        List<GamingQuiz> gamingQuizList = gamingQuizService.selectList(quizEntityWrapper);
        for (GamingQuiz quiz : gamingQuizList) {
            int quizNum = Integer.parseInt(quiz.getFdStartpoint());
            String quizTime = quiz.getFdTime();
            String afterSecond = quiz.getFdSecondResult();
            String gameName = quiz.getFdGameName();
            long newTime = sdf.parse(quizTime).getTime();
            long aaa = newTime + Long.parseLong(afterSecond)*1000;
            long nowtime = new Date().getTime();
            String point = "";
            if(aaa - nowtime <= 0) {
                //查找获奖结果的时间
                String before = sdf.format(new Date(newTime - 1000));
                String after = sdf.format(new Date(newTime + 1000));
                point = redis.hget(gameName, DateUtil.getAfterSecondResult(before, afterSecond));
                if (point == null || point.length() <= 0) {
                    point = redis.hget(gameName, DateUtil.getAfterSecondResult(after, afterSecond));
                    String before1 = sdf.format(new Date(newTime - 2000));
                    String after1 = sdf.format(new Date(newTime + 2000));
                    if (point == null || point.length() <= 0) {
                        point = redis.hget(gameName, DateUtil.getAfterSecondResult(before1, afterSecond));
                        if (point == null || point.length() <= 0) {
                            point = redis.hget(gameName, DateUtil.getAfterSecondResult(after1, afterSecond));
                            if (point == null || point.length() <= 0) {
                                Map<String,String> m = RandomUtil.king();
                                Set<String> set = m.keySet();
                                for(String str : set){
                                    point = m.get(str);
                                }
                            }
                        }
                    }
                }
            }else{
                return;
            }
            Integer result = Integer.parseInt(point);
            UserInfo userInfo = userInfoService.selectById(quiz.getFdUserId());
            float odds = quiz.getFdOdds().floatValue();
            float amount = quiz.getFdAmount().floatValue();
            int type = quiz.getFdType();
            if (type == 0 || type == 1 || type == 2) {
                //单双,大小,特码
                String res = String.valueOf(result);
                computeResult(quiz,res);
            } else if (quiz.getFdType() == 3) {
                //涨
                if(quizNum < result){
                    float winAmount = amount * odds;
                    quiz.setFdResult(1);
                    float over = userInfo.getFdOver().floatValue();
                    float realAmount = over + amount + winAmount;
                    userInfo.setFdOver(BigDecimal.valueOf(realAmount));
                    userInfoService.updateById(userInfo);
                    quiz.setFdMoney(String.valueOf(winAmount));
                } else {
                    quiz.setFdMoney("-"+String.valueOf(amount));
                    quiz.setFdResult(-1);
                }
                quiz.setFdIsSettlement(1);
                quiz.setFdEndpoint(String.valueOf(result));
                gamingQuizService.updateById(quiz);
            } else if (quiz.getFdType() == 4) {
                //跌
                if(quizNum > result){
                    float winAmount = amount * odds;
                    quiz.setFdResult(1);
                    float over = userInfo.getFdOver().floatValue();
                    float realAmount = over + amount + winAmount;
                    userInfo.setFdOver(BigDecimal.valueOf(realAmount));
                    userInfoService.updateById(userInfo);
                    quiz.setFdMoney(String.valueOf(winAmount));
                } else {
                    quiz.setFdMoney(String.valueOf(amount));
                    quiz.setFdResult(-1);
                }
                quiz.setFdIsSettlement(1);
                quiz.setFdEndpoint(String.valueOf(result));
                gamingQuizService.updateById(quiz);
            }
        }
        redisUtil.returnResource(redis);
    }

    void computeResult(GamingQuiz quiz,String result) {
        quiz.setFdEndpoint(result);
        String userId = quiz.getFdUserId();
        UserInfo userInfo = userInfoService.selectById(userId);
        float odds = quiz.getFdOdds().floatValue();
        float amount = quiz.getFdAmount().floatValue();
        //单双
        String quizNum = quiz.getFdQuizNum();
        String gameName = quiz.getFdGameName();
        String quizTime = quiz.getFdTime();
        String afterSecond = quiz.getFdSecondResult();
        result = result.substring(result.length() - 1, result.length());
        if (quizNum.contains(result) || quizNum.equals(result)) {
            float winAmount = amount * odds;
            quiz.setFdResult(1);
            float over = userInfo.getFdOver().floatValue();
            float realAmount = over + amount + winAmount;
            userInfo.setFdOver(BigDecimal.valueOf(realAmount));
            userInfoService.updateById(userInfo);
            quiz.setFdMoney(String.valueOf(winAmount));
        } else {
            quiz.setFdMoney("-"+String.valueOf(amount));
            quiz.setFdResult(-1);
        }
        quiz.setFdIsSettlement(1);
        gamingQuizService.updateById(quiz);
    }

    /**
     * 每天23点59分59秒 更新固定额度
     */
    @Scheduled(cron = "59 59 23 * * ?")
    public void checkMerchantOver(){
        EntityWrapper<MerchantInfo> merchantInfoEntityWrapper = new EntityWrapper<MerchantInfo>();
        merchantInfoEntityWrapper.addFilter("fd_type={0}",0);
        List<MerchantInfo> infoList = merchantInfoService.selectList(merchantInfoEntityWrapper);
        for (MerchantInfo info : infoList){
            float amount = info.getFdAmount().floatValue();
            info.setFdOver(BigDecimal.valueOf(amount));
            merchantInfoService.updateById(info);
        }
    }


    /**
     * 计算大小单双
     *
     * @param totalKillNum 击杀总人数
     * @param sizeScale    大小单双赔率
     * @return
     */
    void computeSize(String totalKillNum, String roomId, float sizeScale) {
        EntityWrapper<BettingRecord> recordEntityWrapper = new EntityWrapper<BettingRecord>();
        recordEntityWrapper.addFilter("fd_type={0} and fd_room_id={1} and fd_is_settlement={2}", 1, roomId, 0);
        List<BettingRecord> recordList = bettingRecordService.selectList(recordEntityWrapper);
        int lastNum = Integer.parseInt(totalKillNum.substring(0,(totalKillNum.length() == 1 ? 2:totalKillNum.length()) - 1));
        //小
        if (lastNum <= 4) {
            String lottery = "01234";
            computeResult(lottery, sizeScale, recordList);
        }
        //大
        if (lastNum >= 5) {
            String lottery = "56789";
            computeResult(lottery, sizeScale, recordList);
        }
        //双
        if (lastNum == 0 || lastNum == 2 || lastNum == 4 || lastNum == 6 || lastNum == 8) {
            String lottery = "02468";
            computeResult(lottery, sizeScale, recordList);
        }
        //单
        if (lastNum == 1 || lastNum == 3 || lastNum == 5 || lastNum == 7 || lastNum == 9) {
            String lottery = "13579";
            computeResult(lottery, sizeScale, recordList);
        }
    }

    /**
     * 更新结果
     * @param lottery
     * @param scale
     * @param recordList
     */
    void computeResult(String lottery, float scale, List<BettingRecord> recordList) {
        for (BettingRecord record : recordList) {
            String bettingNum = record.getFdBettingNum();
            String userId = record.getFdUserId();
            UserInfo userInfo = userInfoService.selectById(userId);
            //是否超额
            scale -= userInfoService.getLimitOdds(userId);
            float bettingAmount = record.getFdBettingAmount().floatValue();
            if (bettingNum.equals(lottery)) {
                record.setFdResult(1);
                record.setFdWinLose(record.getFdBettingAmount());
                record.setFdIsSettlement(1);
                bettingRecordService.updateById(record);
                if (userInfo != null) {
                    float over = userInfo.getFdOver().floatValue();
                    float winAmount = bettingAmount * scale;
                    userInfo.setFdOver(BigDecimal.valueOf(over + winAmount));
                    userInfoService.updateById(userInfo);
                }
            }
            record.setFdResult(-1);
            record.setFdWinLose(record.getFdBettingAmount());
            record.setFdIsSettlement(1);
            bettingRecordService.updateById(record);
        }
    }

    /**
     * 计算胜负
     * @param winId
     * @param scale
     */
    void computeWin(List<BettingRecord> recordList, float scale, String winId) {
        for (BettingRecord record : recordList) {
            String bettingClanId = record.getFdBettingWarId();
            float bettingAmount = record.getFdBettingAmount().floatValue();
            String userId = record.getFdUserId();
            //是否超额
            scale -= userInfoService.getLimitOdds(userId);
            if (bettingClanId.equals(winId)) {
                record.setFdResult(1);
                record.setFdWinLose(record.getFdBettingAmount());
                record.setFdIsSettlement(1);
                UserInfo userInfo = userInfoService.selectById(userId);
                float over = userInfo.getFdOver().floatValue();
                float winAmount = bettingAmount * scale;
                userInfo.setFdOver(BigDecimal.valueOf(over + winAmount));
                userInfoService.updateById(userInfo);
            }
            record.setFdResult(-1);
            record.setFdWinLose(record.getFdBettingAmount());
            record.setFdIsSettlement(1);
            bettingRecordService.updateById(record);

        }

    }


    /**
     * 计算特码
     *
     * @param totalKill
     * @param specialScale
     */
    void computeSpecial(String totalKill, float specialScale, String roomId) {
        EntityWrapper<BettingRecord> recordEntityWrapper = new EntityWrapper<BettingRecord>();
        recordEntityWrapper.addFilter("fd_type={0} and fd_room_id={1} and fd_is_settlement={2}", 3, roomId, 0);
        List<BettingRecord> recordList = bettingRecordService.selectList(recordEntityWrapper);
        String lottery;
        if (totalKill.length() > 1) {
            lottery = totalKill.substring(totalKill.length() - 1, totalKill.length());
            computeResult(lottery, specialScale, recordList);
        } else {
            computeResult(totalKill, specialScale, recordList);
        }
    }

}
